package com.github.lzm320a99981e.autocoding.mavenplugin.mybatisgenerator;

import com.github.lzm320a99981e.autocoding.generator.mybatis.Configuration;
import com.github.lzm320a99981e.autocoding.generator.mybatis.MybatisGenerator;
import lombok.Getter;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.springframework.beans.BeanUtils;

import java.io.File;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Objects;
import java.util.Properties;

import static freemarker.template.Configuration.VERSION_2_3_28;

@Getter
@Mojo(name = "generate", threadSafe = true)
public class MybatisGeneratorMojo extends AbstractMojo {
    /**
     * 属性配置
     */
    @Parameter(property = "properties")
    private Properties properties;

    /**
     * JDBC 连接配置
     */
    @Parameter(property = "jdbc", required = true)
    private Configuration.Jdbc jdbc;

    /**
     * 指定数据库
     */
    @Parameter(property = "schema")
    private String schema;

    /**
     * 模板目录
     */
    @Parameter(property = "templateDirectory")
    private File templateDirectory;

    /**
     * 实体生成配置
     */
    @Parameter(property = "model")
    private Configuration.GenerateJava model;

    /**
     * 数据库操作接口代码生成配置
     */
    @Parameter(property = "repository")
    private Configuration.GenerateJava repository;

    /**
     * 基础服务层代码生成配置
     */
    @Parameter(property = "service")
    private Configuration.GenerateJava service;

    /**
     * 数据库SQL代码生成配置
     */
    @Parameter(property = "repositorySql")
    private Configuration.GenerateXml repositorySql;

    /**
     * 自定义数据库SQL代码生成配置
     */
    @Parameter(property = "repositoryCustomSql")
    private Configuration.GenerateXml repositoryCustomSql;

    /**
     * 保留标记开始
     */
    @Parameter(property = "keepMarkStart")
    private String keepMarkStart = "KEEP_MARK_START";

    /**
     * 保留标记结束
     */
    @Parameter(property = "keepMarkEnd")
    private String keepMarkEnd = "KEEP_MARK_END";

    /**
     * 数据库表匹配
     */
    @Parameter(property = "tableNamePattern")
    private String tableNamePattern;

    /**
     * 数据库表配置
     */
    @Parameter(property = "tables")
    private List<Configuration.Table> tables;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        // 复制配置信息
        final Configuration mybatisGeneratorConfiguration = new Configuration();
        BeanUtils.copyProperties(this, mybatisGeneratorConfiguration);
        mybatisGeneratorConfiguration.setCatalog(schema);
        mybatisGeneratorConfiguration.setSchemaPattern(schema);

        // 模板初始化处理
        if (Objects.isNull(mybatisGeneratorConfiguration.getTemplateConfiguration())) {
            freemarker.template.Configuration templateConfiguration = new freemarker.template.Configuration(VERSION_2_3_28);
            templateConfiguration.setClassForTemplateLoading(getClass(), "templates");
            mybatisGeneratorConfiguration.setTemplateConfiguration(templateConfiguration);
            /**
             * 按照约定将 {@link Configuration.GenerateFile} 类型的字段名称与模板名称设置成一致
             * 例如：model.ftl 将对应 {@link Configuration.GenerateJava model} 字段
             */
            final Field[] fields = mybatisGeneratorConfiguration.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (Configuration.Template.class.isAssignableFrom(field.getType())) {
                    try {
                        field.setAccessible(true);
                        Configuration.Template template = (Configuration.Template) field.get(mybatisGeneratorConfiguration);
                        if (Objects.isNull(template)) {
                            continue;
                        }
                        template.setTemplate(field.getName() + ".ftl");
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }

        // 执行
        MybatisGenerator.create(mybatisGeneratorConfiguration).generate();
    }
}
